#include <iostream>

#include <jvmti.h>
#include <jni_md.h>
#include <jni.h>

static jvmtiEnv *jvmti;

extern "C"
int init_agent(JavaVM *vm, void *reserved) {
    jint rc;
    /* Get JVM TI environment */
    rc = vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_2);
    if (rc != JNI_OK) {
        fprintf(stderr, "ERROR: simple vmtool Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc);
        return -1;
    }

    jvmtiCapabilities capabilities = {0};
    capabilities.can_tag_objects = 1;
    jvmtiError error = jvmti->AddCapabilities(&capabilities);
    if (error) {
        fprintf(stderr, "ERROR: simple vmtool JVMTI AddCapabilities failed!%u\n", error);
        return JNI_FALSE;
    }

    return JNI_OK;
}

extern "C"
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM* vm, void* reserved) {
    init_agent(vm, reserved);
    return JNI_VERSION_1_6;
}

extern "C"
JNIEXPORT jobjectArray
JNICALL Java_org_jlamp_server_vm_VmTool_getAllThreads (JNIEnv *env) {
    jthread *threads;
    jint count = 0;

    jvmtiError err = (jvmtiError) 0;
    err = jvmti->GetAllThreads(&count, &threads);
    if (err) {
        printf("ERROR: JVM TI GetAllThreads failed!\n");
        return NULL;
    }

    jclass clsThread = env->FindClass("java/lang/Thread");
    jobjectArray array = env->NewObjectArray(count, clsThread, NULL);
    for (int i = 0; i < count; i++) {
        env->SetObjectArrayElement(array, i, threads[i]);
    }

    return array;
}